package com.huosu.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.setting.Setting;
import com.huosu.commons.enums.SysTypeEnum;
import com.huosu.domain.Version;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.ArrayList;
import java.util.List;


/**
 * @program: miner-shield-web-v2
 * @description:
 * @author: changlin
 * @create: 2019-12-17 13:45
 **/
@Slf4j
public class UpgradeUtil {

    /**
     * 升级
     *
     * @param
     * @return
     */
    public static boolean upgrade_v2(Version version, String settingPath) {

        Setting setting = new Setting(FileUtil.touch(settingPath), CharsetUtil.CHARSET_UTF_8, true);

        String download_dir = setting.get(version.getTypeEName(), "download_dir");

        File f = new File(download_dir);

        if (!f.exists()) {
            f.mkdirs();
            log.info("创建下载文件夹!");
        }

        //删除更新包
        FileUtil.del(download_dir + version.getFileName());

        //下载更新包
        down(version.getUrl(), download_dir);

        //down_java(version.getUrl(), download_dir);

        String down_file_md5 = MD5Util.getFileMD5(new File(download_dir + version.getFileName()));

        log.info("version.getMd5() {} md5 {}", version.getMd5(), down_file_md5);

        if (version.getMd5().equals(down_file_md5)) {
            log.info("Check md5 OK.");
        } else {
            log.info("Check md5 fail.");
            FileUtil.del(download_dir + version.getFileName());
            log.info("del " + download_dir + version.getFileName());
            return false;
        }

        log.info("下载文件完成!");
        return true;
    }

    /**
     * 重启
     *
     * @param
     * @return
     */
    public static boolean restart_v2(Version version, String settingPath) {

        Setting setting = new Setting(FileUtil.touch(settingPath), CharsetUtil.CHARSET_UTF_8, true);

        String download_dir = setting.get(version.getTypeEName(), "download_dir");
        String run_dir = setting.get(version.getTypeEName(), "run_dir");
        String back_dir = setting.get(version.getTypeEName(), "back_dir");

        String down_file_path = download_dir + version.getFileName();

        File f = new File(down_file_path);

        if (f.exists()) {
            String down_file_md5 = MD5Util.getFileMD5(new File(download_dir + version.getFileName()));
            if (version.getMd5().equals(down_file_md5)) {
                log.info("MD5校验完成");
                //解压文件夹
                String out_file_path = download_dir + version.getPublishVersion();
                File versionDir = new File(out_file_path);
                //有 删除
                if (versionDir.exists()) {
                    FileUtil.del(versionDir);
                    log.info("删除解压文件夹完成");
                }
                //创建版本目录
                FileUtil.mkdir(versionDir);
                log.info("创建解压文件夹完成");
                //解压
                ZipUtil.unzip(down_file_path, out_file_path);
                log.info("解压文件完成");
                //授权
                ShellUtil.execShellWithResult("chmod -R 755 " + out_file_path);
                log.info("文件授权完成");
                //备份文件夹
                String back_file_path = back_dir + File.separator + version.getLocalVersion();
                File backDir = new File(back_file_path);
                if (!backDir.exists()) {
                    FileUtil.mkdir(backDir);
                    log.info("创建备份文件夹完成");
                }
                //备份文件
                ZipUtil.zip(run_dir, back_file_path + File.separator + version.getTypeEName() + ".zip");
                log.info("备份文件完成");
                //拷贝
                String cmd = StrUtil.format("{}/*", out_file_path);
                log.info("拷贝 {}", cmd);
                //ShellUtil.execShell("/home/upgrade/cp_file.sh", true, cmd, run_dir);
                copy(cmd, run_dir);
                log.info("拷贝文件完成");
                //重启
                if (SysTypeEnum.data.getValue().equals(version.getTypeEName())) {
                    ShellUtil.execCommand("supervisorctl restart miningshield");
                }

                if (SysTypeEnum.web.getValue().equals(version.getTypeEName())) {
                    setting.set("db", "update_version", version.getPublishVersion());
                    setting.store(settingPath);
                }

                if (SysTypeEnum.other.getValue().equals(version.getTypeEName())) {
                    String currentSh = out_file_path + File.separator + "sh" + File.separator + version.getPublishVersion() + ".sh";
                    log.info("currentSh {}", currentSh);
                    if (FileUtil.exist(currentSh)) {
                        ShellUtil.execShell(currentSh, true);
                        log.info("版本sh执行完成");
                    }
                }
                log.info("restart_v2 完成");
                return true;
            } else {
                log.error("Check md5 fail.");
                return false;
            }
        } else {
            log.error("file not find");
            return false;
        }
    }


    /**
     * 版本比较 前者大则返回一个正数,后者大返回一个负数,相等则返回0
     *
     * @param v1
     * @param v2
     * @return
     */
    public static int compareVersion(String v1, String v2) {
        if (v1.equals(v2)) {
            return 0;
        }
        String[] version1Array = v1.split("[._]");
        String[] version2Array = v2.split("[._]");
        int index = 0;
        int minLen = Math.min(version1Array.length, version2Array.length);
        long diff = 0;

        while (index < minLen
                && (diff = Long.parseLong(version1Array[index])
                - Long.parseLong(version2Array[index])) == 0) {
            index++;
        }
        if (diff == 0) {
            for (int i = index; i < version1Array.length; i++) {
                if (Long.parseLong(version1Array[i]) > 0) {
                    return 1;
                }
            }

            for (int i = index; i < version2Array.length; i++) {
                if (Long.parseLong(version2Array[i]) > 0) {
                    return -1;
                }
            }
            return 0;
        } else {
            return diff > 0 ? 1 : -1;
        }
    }

    /**
     * 获取升级文件 排序
     *
     * @param currVersion 当前版本
     * @param distVersion 目标版本
     * @param path        文件路径
     * @param type        文件类型
     * @return
     */
    public static String[] getUpgradeFileSort(String currVersion, String distVersion, String path, String type) {
        type = "." + type;
        List<String> fileList = FileUtil.listFileNames(path);
        List<String> tempList = new ArrayList<>();
        for (String fi : fileList) {
            String fileName = fi.toLowerCase();
            if (fileName.endsWith(type)) {
                String sqlVersion = fileName.replaceAll(type, "");
                if (compareVersion(sqlVersion, currVersion) > 0 && compareVersion(sqlVersion, distVersion) <= 0) {
                    tempList.add(sqlVersion);
                }
            }
        }
        String[] upgradeFile = tempList.toArray(new String[tempList.size()]);
        upgradeFile = sortPlus(upgradeFile);
        return upgradeFile;
    }

    public static String[] sortPlus(String[] arr) {
        if (arr != null && arr.length > 1) {
            for (int i = 0; i < arr.length - 1; i++) {
                // 初始化一个布尔值
                boolean flag = true;
                for (int j = 0; j < arr.length - i - 1; j++) {
                    if (compareVersion(arr[j], arr[j + 1]) > 0) {
                        // 调换
                        String temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                        // 改变flag
                        flag = false;
                    }
                }
                if (flag) {
                    break;
                }
            }
        }

        return arr;
    }

    /**
     * 下载文件
     *
     * @param fileUrl
     * @param savePath
     * @return
     */
    public static boolean down(String fileUrl, String savePath) {
        log.info("开始下载 {}", fileUrl);
        String fileName = StrUtil.subSuf(fileUrl, fileUrl.lastIndexOf('/') + 1);
        String wget = "/home/other/wget.sh";

        if (!FileUtil.exist(wget)) {
            FileUtil.touch(wget);
            List<String> list = new ArrayList<>();
            list.add("#!/bin/sh");
            list.add("wget -q $1 -O $2");
            FileUtil.writeUtf8Lines(list, wget);
            ShellUtil.execShellWithResult("chmod -R 755 " + wget);
        } else {
            String wgetMd5 = "3fa4d14fceb2b1e4f2e1c8bd605e63a0";
            String md5 = MD5Util.getFileMD5(FileUtil.file(wget));
            if (!md5.equals(wgetMd5)) {
                FileUtil.clean(wget);
                List<String> list = new ArrayList<>();
                list.add("#!/bin/sh");
                list.add("wget -q $1 -O $2");
                FileUtil.writeUtf8Lines(list, wget);
                ShellUtil.execShellWithResult("chmod -R 755 " + wget);
            }
        }

        ShellUtil.execShell(wget, true, fileUrl, savePath + fileName);
        log.info("下载完成！{}", fileUrl);
        return true;
    }

    /**
     * 拷贝文件
     *
     * @return
     */
    public static boolean copy(String filePath, String savePath) {
        String cpFile = "/home/upgrade/cp_file.sh";
        if (!FileUtil.exist(cpFile)) {
            FileUtil.touch(cpFile);
            List<String> list = new ArrayList<>();
            list.add("#!/bin/sh");
            list.add("cp -rfp $1 $2");
            FileUtil.writeUtf8Lines(list, cpFile);
            ShellUtil.execShellWithResult("chmod -R 755 " + cpFile);
        } else {
            String cpFileMd5 = "53920d972918e143bc05012dd8445b26";
            String md5 = MD5Util.getFileMD5(FileUtil.file(cpFile));
            if (!md5.equals(cpFileMd5)) {
                FileUtil.clean(cpFile);
                List<String> list = new ArrayList<>();
                list.add("#!/bin/sh");
                list.add("cp -rfp $1 $2");
                FileUtil.writeUtf8Lines(list, cpFile);
                ShellUtil.execShellWithResult("chmod -R 755 " + cpFile);
            }
        }
        ShellUtil.execShell(cpFile, true, filePath, savePath);
        log.info("拷贝文件！{}", filePath);
        return true;
    }

}
